import tkinter as tk
from tkinter import messagebox
import random
import queue


class Customer:
    def __init__(self, arrival_time, service_type):
        self.arrival_time = arrival_time
        self.service_type = service_type


class BankWindow:
    def __init__(self):
        self.is_busy = False
        self.current_customer = None
        self.total_customers_served = 0
        self.total_deposit_customers = 0
        self.total_withdrawal_customers = 0
        self.total_report_loss_customers = 0
        self.total_repay_loan_customers = 0

    def serve_customer(self, customer):
        self.is_busy = True
        self.current_customer = customer
        self.total_customers_served += 1
        if customer.service_type == "Deposit":
            self.total_deposit_customers += 1
        elif customer.service_type == "Withdrawal":
            self.total_withdrawal_customers += 1
        elif customer.service_type == "Report Loss":
            self.total_report_loss_customers += 1
        elif customer.service_type == "Repay Loan":
            self.total_repay_loan_customers += 1

    def finish_serving_customer(self):
        self.is_busy = False
        self.current_customer = None


class BankSimulationApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Bank Simulation")

        self.setup_frame = tk.Frame(self.root)
        self.setup_frame.pack(pady=20)

        tk.Label(self.setup_frame, text="Customers per Hour:").grid(row=0, column=0)
        self.customers_per_hour_entry = tk.Entry(self.setup_frame)
        self.customers_per_hour_entry.grid(row=0, column=1)
        self.customers_per_hour_entry.insert(tk.END, "10")

        tk.Button(self.setup_frame, text="Start Simulation", command=self.start_simulation).grid(row=1, columnspan=2)

        self.result_frame = tk.Frame(self.root)

    def start_simulation(self):
        try:
            customers_per_hour = int(self.customers_per_hour_entry.get())
            self.simulate_bank(customers_per_hour)
        except ValueError:
            messagebox.showerror("Error", "Invalid input for customers per hour.")

    def simulate_bank(self, customers_per_hour):
        bank_windows = [BankWindow() for _ in range(4)]
        waiting_customers = queue.Queue()
        total_waiting_time = 0
        total_customers = 0

        for hour in range(8):
            for _ in range(customers_per_hour):
                arrival_time = hour + random.random()
                service_type = random.choice(["Deposit", "Withdrawal", "Report Loss", "Repay Loan"])
                customer = Customer(arrival_time, service_type)
                waiting_customers.put(customer)
                total_customers += 1

            for window in bank_windows:
                if not window.is_busy and not waiting_customers.empty():
                    next_customer = waiting_customers.get()
                    wait_time = hour + random.random() - next_customer.arrival_time
                    total_waiting_time += wait_time
                    window.serve_customer(next_customer)

            for window in bank_windows:
                if window.is_busy:
                    # Assuming a fixed service time for each type of service
                    service_time = random.uniform(0.5, 2.0)
                    if hour + random.random() >= service_time:
                        window.finish_serving_customer()

        avg_waiting_time = total_waiting_time / total_customers
        result_text = f"Average waiting time: {avg_waiting_time:.2f}\n\n"
        for i, window in enumerate(bank_windows):
            result_text += f"Window {i + 1}:\n"
            result_text += f"- Total customers served: {window.total_customers_served}\n"
            result_text += f"- Deposit customers: {window.total_deposit_customers}\n"
            result_text += f"- Withdrawal customers: {window.total_withdrawal_customers}\n"
            result_text += f"- Report loss customers: {window.total_report_loss_customers}\n"
            result_text += f"- Repay loan customers: {window.total_repay_loan_customers}\n\n"

        self.result_frame.destroy()
        self.result_frame = tk.Frame(self.root)
        self.result_frame.pack(pady=20)
        tk.Label(self.result_frame, text=result_text, justify=tk.LEFT).pack()


def main():
    root = tk.Tk()
    app = BankSimulationApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()
